package com.guet;

import javax.swing.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class algorithm {
    //找出最短路线:Dijkstra
    public MGraph mGraph=new MGraph();
    public int driveTimeArgs[][]=new int[mGraph.vexNum*2][mGraph.vexNum*2];
    int position[][]=new int[mGraph.vexNum*2][mGraph.vexNum*2];
    private int driveSpeed=6;
    private int cycling=4;
    private int walkSpeed=2;
    String times[]={"当前时间","00:00 ~ 11:15","11:15 ~ 13:00",
            "13:00 ~ 14:00","14:00 ~ 15:00","15:00 ~ 17:35",
            "17:35 ~ 20:00","20:00 ~ 21:40","21:40 ~ 22:00","22:00 ~ 24:00"};
    List<String> Crowded=new fileUse().getCrowded();

    public List<Integer> Dijkstra(String startName,String endName,String way){
        int start=0;
        int end=0;
        for(vexsinfo v:mGraph.vexs.values()){
            if(v.name.equals(startName)){
                start=v.id;
            }else if(v.name.equals(endName)){
                end=v.id;
            }
        }
        //弗洛伊德算法
        boolean[] selected=new boolean[mGraph.vexNum*2];
        int[] minCost=new int[mGraph.vexNum*2];
        int[] parent=new int[mGraph.vexNum*2];
        Arrays.fill(selected,false);
        Arrays.fill(minCost,65535);
        Arrays.fill(parent,-1);
        minCost[start]=0;
        Queue<Integer> queue=new LinkedList<>();
        queue.offer(start);
        while(!queue.isEmpty()){
            int currentId=queue.poll(); //出最小边到达的顶点
            int direction[]={mGraph.vexs.get(currentId).top,mGraph.vexs.get(currentId).bottom,mGraph.vexs.get(currentId).left,mGraph.vexs.get(currentId).right};
            for(int i=0;i<direction.length;i++){
                if(direction[i]==-1)continue;
                int drive=way.equals("步行")?1:mGraph.vexs.get(direction[i]).drive;
                if( drive==1&&selected[currentId]!=true&&mGraph.arcs[currentId][direction[i]]+minCost[currentId]<minCost[direction[i]]){
                    minCost[direction[i]]=mGraph.arcs[currentId][direction[i]]+minCost[currentId];  //更新到direction[i]的距离
                    parent[direction[i]]=currentId; //更新到direction[i]的来源
                    queue.add(direction[i]);
                }
            }
            selected[currentId]=true;
        }
        if(minCost[end]==65535){
            JOptionPane.showMessageDialog(null,"无法到达");
            return null;
        }
        List<Integer> list= new LinkedList<>();

        while (end!=-1){  //当该end的父亲结点为-1不存在时
            list.add(end);
            end=parent[end];
        }

        String name=mGraph.vexs.get(start).name;
        for(int i=list.size()-1;i>=0;i--){
            name=mGraph.vexs.get(list.get(i)).name;
            System.out.print(name+"->");
        }
        System.out.println();
        return list;
    }
    public List<Integer> Floyd(String startName,String endName){
        List<Integer> list=new ArrayList<>();
        for(vexsinfo v:mGraph.vexs.values()){
            for(int j=1;j<driveTimeArgs[v.id].length;j++){
                position[v.id][j]=j;
                driveTimeArgs[v.id][j]=65535;
            }
            int dir[]={v.left,v.right,v.top,v.bottom};
            for (int i=0;i<4;i++){
                if(dir[i]==-1)continue;
                vexsinfo v1=mGraph.vexs.get(dir[i]);
                if(v1.drive==0){
                    continue;
                }
                int speed;
                speed=driveSpeed/(int)(v.croded_level>v1.croded_level?v.croded_level:v1.croded_level);
                int t=mGraph.arcs[v.id][v1.id]/speed+1;
                driveTimeArgs[v.id][v1.id]=t;
            }
        }
        //迪杰斯特拉算法
        for(int k=1;k<driveTimeArgs.length;k++){
            for(int i=1;i<driveTimeArgs.length;i++){
                for(int j=1;j<driveTimeArgs.length;j++){
                    if(driveTimeArgs[k][j]+driveTimeArgs[i][k]<driveTimeArgs[i][j] ){
                        driveTimeArgs[i][j]=driveTimeArgs[k][j]+driveTimeArgs[i][k];
                        position[i][j]=position[i][k];
                    }
                }
            }
        }
        int start=0,end=0;
        for(vexsinfo v:mGraph.vexs.values()){
            if(v.name.equals(startName))start=v.id;
            else if(v.name.equals(endName))end=v.id;
        }
        list.add(start);
        String name=mGraph.vexs.get(start).name;
        while(position[start][end]!=end){
            System.out.print(name+"->");
            start=position[start][end];
            list.add(start);
        }
        System.out.println();
        list.add(end);
        return list;
    }
    public int getListIdsDistance(List<Integer> ids){
        int s=0;
        for(int i=1;i<ids.size();i++){
            s+=mGraph.arcs[ids.get(i)][ids.get(i-1)];
        }
        return s;
    }

    public void setCrowdingDegree(String periodFind){
        int i=getWhereInTimes(periodFind);
        if(i%2!=0){//路段都不拥挤
            for(vexsinfo v:mGraph.vexs.values()){
                v.croded_level=1.0F;
            }
        }else{ //设置拥挤路段
            for(vexsinfo v:mGraph.vexs.values()){
                if(Crowded.contains(v.name))
                    v.croded_level=2.0F;
            }
        }
    }
    public int getWhereInTimes(String periodFind){
        int i;
        DateFormat df = new SimpleDateFormat("hh:mm");
        if(periodFind.equals(times[0])){
            Date date=new Date();
            String strNowTime=df.format(date);
            for(i=1;i<=9;i++){
                try {
                    Date time=df.parse(times[i].split(" ")[0]);
                    Date nowTime=df.parse(strNowTime);
                    if(time.after(nowTime)){  //表示startTime晚于endTime
                        i--;
                        break;
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }else{
            for(i=1;i<=9;i++){
                Date time= null;
                Date nowTime=null;
                try {
                    time = df.parse(times[i].split(" ")[0]);
                    nowTime=df.parse(periodFind);
                    if(time.after(nowTime)){  //表示startTime早于endTime
                        i--;
                        break;
                    }else if(time.equals(nowTime)){
                        break;
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }
        return i;
    }
    public double getSpeed(String goWay,String periodFind,int startId,int positionId){
        setCrowdingDegree(periodFind);
        int Speed=walkSpeed;
        if(goWay.equals("骑行")){
            Speed=cycling;
        }else if(goWay.equals("驾车")){
            Speed=driveSpeed;
        }else{
            return  Speed;
        }
        return  Speed/Math.max(mGraph.vexs.get(positionId).croded_level,mGraph.vexs.get(startId).croded_level);
    }
    public int getTwoPTime(String startName,String endName){
        int start=0,end=0;
        for(vexsinfo v:mGraph.vexs.values()){
            if(v.name.equals(startName))start=v.id;
            else if(v.name.equals(endName))end=v.id;
        }
        return driveTimeArgs[start][end];
    }
    public int getListTime(List<Integer> ids,String goWay,String period){
        double sumTime=0;
        int start=ids.get(0);
        for(int i=1;i<ids.size();i++){
            int end=ids.get(i);
            sumTime+=mGraph.arcs[start][end]/ getSpeed(goWay,period,start,end);
            start=end;
        }
        return (int) sumTime;
    }
    public String messageCrowded(List<Integer> list , String time){
        setCrowdingDegree(time);
        for(int id:list){
            if(mGraph.vexs.get(id).croded_level>1.5){
                return "提示：该条路线存在上下课高峰期路段";
            }
        }
        if(time.equals(times[0])){
            String date=new SimpleDateFormat("hh:mm").format(new Date());
            int shi=Integer.parseInt(date.split(":")[0]);
            int fen=Integer.parseInt(date.split(":")[1])+10;
            if(fen>=60)shi++;
            time=shi+":"+fen;
            int i=getWhereInTimes(date);
            if(i%2==0){
                return "该路线十分钟后可能存在高峰路段";
            }
        }
        return  "";
    }
}
